package model.session;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.concurrent.Semaphore;

import model.cnf.CNF;
import model.solver.SolverResult;
import controller.solver.Solver;
import controller.xml.XMLBaliseFormat;

/**
 * <p>
 * A {@link SessionBlock} that represent a execution of a solver.
 * </p>
 * <p>
 * Don't forget to set the cnf and {@link Semaphore} before executing it.
 * </p>
 * 
 * @author GRONOWSKI Stephane svan001@aol.com
 * 
 *         igsat 2010
 * 
 */
public class SolverExecutionBlock extends ExecutableSessionBlock {

	private Solver			solver;
	private SolverResult	res;
	private CNF				cnf;

	/**
	 * create a {@link SolverExecutionBlock}.
	 * 
	 * @param first
	 *            the first session block see {@link SessionBlock}
	 * @param status
	 *            the status
	 * @param solver
	 *            the solver that has been used
	 * @param res
	 *            the result of the execution
	 */
	public SolverExecutionBlock(SessionBlock first, ExecutionStatus status, Solver solver, SolverResult res) {
		super(first, status);

		if (solver == null)
			throw new IllegalArgumentException();
		this.solver = solver;
		this.res = res;
		description = solver.toString();
	}

	/**
	 * Export the data in XML
	 * 
	 * @param file
	 *            {@link BufferedWriter} to write
	 * @throws IOException
	 */
	@Override
	public void exportXML(BufferedWriter file) throws IOException {

		// open
		// file.newLine();
		file.write("<" + XMLBaliseFormat.SOLVER_EXECUTION + ">");

		// basic
		super.exportXML(file);

		// res
		res.exportXML(file);

		// solver
		solver.exportXML(file);

		// close
		// file.newLine();
		file.write("</" + XMLBaliseFormat.SOLVER_EXECUTION + ">");
	}


	/**
	 * Return the solver that was executed.
	 * 
	 * @return the solver that was executed.
	 */
	public Solver getSolver() {
		return solver;
	}

	/**
	 * Return the result of the execution.
	 * 
	 * @return the result of the execution.
	 */
	public SolverResult getRes() {
		return res;
	}

	/**
	 * Return the cnf on witch it was executed.
	 * 
	 * @return the cnf on witch it was executed.
	 */
	public CNF getCnf() {
		return cnf;
	}

	/**
	 * Set the cnf on witch it supposed to be executed.
	 * 
	 * @param cnf
	 *            the cnf to set
	 */
	public void setCnf(CNF cnf) {
		this.cnf = cnf;
	}

	@Override
	public void run() {
		/*
		 * try { sem.acquire(); } catch (InterruptedException e1) { e1.printStackTrace(); status =
		 * ExecutionStatus.PROBLEM; listener.reportEndExec(this); return; }
		 */
		if (listener == null || cnf == null)
		{// pb pas de listener
			status = ExecutionStatus.PROBLEM;
			if (sem != null)
				sem.release();
			res = null;
			if (listener != null)
				listener.reportEndExec(this);
			return;
		}

		status = ExecutionStatus.RUNNING;

		try
		{
			res = solver.evaluate(cnf, sem);
			status = ExecutionStatus.FINISH;

		} catch (Exception e)
		{
			e.printStackTrace();
			res = null;
			status = ExecutionStatus.PROBLEM;
		}
		finally
		{
			listener.reportEndExec(this);
		}
	}

	@Override
	public void stopExecution() {
		System.out.println("appelle stop execution");
		solver.stop();
		status = ExecutionStatus.FINISH;

	}

	@Override
	public long getTotalExecutionTime() {
		if (res != null)
			return previousExecutionTime + res.getExecutionTime();

		return previousExecutionTime;
	}

}
